package functionalOptions

import "fmt"

type Connection struct{}
type StuffClient interface {
	DoStuff() error
}
type stuffClient struct{
	conn Connection
	retries int
	timeout int
}
type StuffClientOptions struct {
	Retries int
	Timeout int
}
//第一种这样定义,但是不方便在, 非必填参数没有默认值
func NewStuffClient1(conn Connection, timeout, retries int) *stuffClient{
	return &stuffClient{
		conn: conn,
		timeout: timeout,
		retries: retries,
	}
}
//第二种,将非必填参数放入单独结构体,看起来不错,但第一个方式的问题还存在
func NewStuffClient2(conn Connection, options StuffClientOptions) *stuffClient{
	return &stuffClient{
		conn: conn,
		timeout: options.Timeout,
		retries: options.Retries,
	}
}
//第三种,将非必填参数放入单独结构体,并再创建一个functional options 的 StuffClientOption结构体
//functional options
type StuffClientOption func(options *StuffClientOptions)
func WithRetries(r int) StuffClientOption{
	return func(o *StuffClientOptions) {
		o.Retries = r
	}
}
func WithTimeout(t int)StuffClientOption{
	return func(o *StuffClientOptions) {
		o.Timeout = t
	}
}
var defaultStuffClientOptions = StuffClientOptions{
	Retries: 3,
	Timeout: 3,
}
func NewStuffClient3(conn Connection, opts ...StuffClientOption) *stuffClient{
	options := defaultStuffClientOptions
	for _,o := range opts{
		o(&options)
	}
	return &stuffClient{
		conn: conn,
		timeout: options.Timeout,
		retries: options.Retries,
	}
}

func Do(){
	x := NewStuffClient3(Connection{})
	fmt.Println(x)
	x = NewStuffClient3(Connection{}, WithTimeout(3))
	x = NewStuffClient3(Connection{}, WithRetries(2))
}